package com.xbongbong.paas.enums;

import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import lombok.Getter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 回款单类型枚举
 * @author zhouwq
 * @date 2019/10/31 15:39
 */

@Getter
public enum PaymentSheetTypeEnum {

    /**
     * code："1"
     * 已核销（已核销的alias没有用XbbRefTypeEnum.PAYMENT_SHEET的alias）
     * 入口：回款单列表、合同详情、应收款列表、应收款详情、客户详情
     * 回款，直接核销。此类回款单是原线上已有流程业务，新建回款单时必须关联客户、合同(可关联应收款)，故而将称之为“直接核销”回款单
     */
    WRITE_OFF(SheetTypeEnum.WRITE_OFF.getCode(), SheetTypeEnum.WRITE_OFF.getI18nName(), SheetTypeEnum.WRITE_OFF.getAlias(), XbbRefTypeEnum.PAYMENT_SHEET.getCode(), SheetTypeEnum.WRITE_OFF),

    /**
     * code："2"
     * 预收款核销
     * 入口：预收款列表、预收款明细、客户详情、合同详情
     */
    WRITE_OFF_PREPAYMENT(SheetTypeEnum.WRITE_OFF_PREPAYMENT.getCode(), SheetTypeEnum.WRITE_OFF_PREPAYMENT.getI18nName(), SheetTypeEnum.WRITE_OFF_PREPAYMENT.getAlias(), XbbRefTypeEnum.WRITE_OFF_PREPAYMENT.getCode(), SheetTypeEnum.WRITE_OFF_PREPAYMENT),

    /**
     * code："3"
     * 预收款
     * 入口：预收款列表
     */
    PREPAYMENT(SheetTypeEnum.PREPAYMENT.getCode(), SheetTypeEnum.PREPAYMENT.getI18nName(), SheetTypeEnum.PREPAYMENT.getAlias(), XbbRefTypeEnum.PREPAYMENT.getCode(), SheetTypeEnum.PREPAYMENT),

    /**
     * code："4","5","6","8"
     * 红冲（红冲已核销的alias没有用XbbRefTypeEnum.RED_WRITE_OFF的alias）
     * 入口：原回款单详情、预收款明细、预收款核销单详情、新建退款退款时-红冲
     */
    //"4"，红冲已核销
    RED_WRITE_OFF(SheetTypeEnum.RED_WRITE_OFF.getCode(), SheetTypeEnum.RED_WRITE_OFF.getI18nName(), SheetTypeEnum.RED_WRITE_OFF.getAlias(), XbbRefTypeEnum.RED_PAYMENT_SHEET.getCode(), SheetTypeEnum.RED_WRITE_OFF),
    //"5"，红冲预收款核销
    RED_WRITE_OFF_PREPAYMENT(SheetTypeEnum.RED_WRITE_OFF_PREPAYMENT.getCode(), SheetTypeEnum.RED_WRITE_OFF_PREPAYMENT.getI18nName(), SheetTypeEnum.RED_WRITE_OFF_PREPAYMENT.getAlias(), XbbRefTypeEnum.RED_WRITE_OFF_PREPAYMENT.getCode(), SheetTypeEnum.RED_WRITE_OFF_PREPAYMENT),
    //"6"，红冲预收款余额
    RED_PREPAYMENT(SheetTypeEnum.RED_PREPAYMENT.getCode(), SheetTypeEnum.RED_PREPAYMENT.getI18nName(), SheetTypeEnum.RED_PREPAYMENT.getAlias(), XbbRefTypeEnum.RED_PREPAYMENT.getCode(), SheetTypeEnum.RED_PREPAYMENT),
    //"8"，新增一种回款单类型：红冲预收款核销(退到余额)
    RED_WRITE_OFF_BALANCE(SheetTypeEnum.RED_WRITE_OFF_BALANCE.getCode(), SheetTypeEnum.RED_WRITE_OFF_BALANCE.getI18nName(), SheetTypeEnum.RED_WRITE_OFF_BALANCE.getAlias(), XbbRefTypeEnum.RED_WRITE_OFF_BALANCE.getCode(), SheetTypeEnum.RED_WRITE_OFF_BALANCE),

    /**
     * code："7"
     * 坏账
     * 入口：合同详情、应收款详情
     */
    BAD_PAYMENT(SheetTypeEnum.BAD_PAYMENT.getCode(), SheetTypeEnum.BAD_PAYMENT.getI18nName(), SheetTypeEnum.BAD_PAYMENT.getAlias(), XbbRefTypeEnum.BAD_DEBT.getCode(), SheetTypeEnum.BAD_PAYMENT),

    /**
     * 未知
     */
    UNKNOWN(SheetTypeEnum.UNKNOWN.getCode(), SheetTypeEnum.UNKNOWN.getI18nName(), XbbRefTypeEnum.UNKNOWN.getAlias(), XbbRefTypeEnum.UNKNOWN.getCode(), SheetTypeEnum.UNKNOWN),
    ;

    /**
     * 类型code值
     */
    private String code;

    /**
     * 类型名称
     */
    private String name;

    /**
     * 类型attr
     */
    private String alias;

    /**
     * 业务code
     */
    private Integer businessType;

    /**
     * 回款单、付款单总枚举
     */
    private SheetTypeEnum sheetTypeEnum;

    PaymentSheetTypeEnum(String code, String name, String alias, Integer businessType, SheetTypeEnum sheetTypeEnum){
        this.code = code;
        this.name = name;
        this.alias = alias;
        this.businessType = businessType;
        this.sheetTypeEnum = sheetTypeEnum;
    }

    /**
     * 根据回款单类型判断是否为红冲类型
     * @param type 回款单类型
     * @return 是否为红冲 true为红冲
     * @author zhouwq
     * @date 2019/10/31 15:53
     */
    public static boolean isRed(String type){
        return Objects.equals(type, RED_PREPAYMENT.code) || Objects.equals(type, RED_WRITE_OFF_PREPAYMENT.code) || Objects.equals(type, RED_WRITE_OFF_BALANCE.code) || Objects.equals(type, RED_WRITE_OFF.code);
    }

    /**
     * 根据回款单类型判断是否为核销类型（不包含预收款回款单类型）
     * @param type 回款单类型
     * @return 是否为核销 true为核销
     * @author zhouwq
     * @date 2019/10/31 15:53
     */
    public static boolean isWriteOff(String type){
        return Objects.equals(type, WRITE_OFF.code) || Objects.equals(type, WRITE_OFF_PREPAYMENT.code);
    }

    /**
     * 根据businessType判断是否为红冲类型
     * @param businessType 业务code
     * @return 是否为红冲
     * @author zhouwq
     * @date 2019/12/12 11:35
     */
    public static boolean isRedByBusinessType(Integer businessType) {
        return Objects.equals(businessType, RED_PREPAYMENT.getBusinessType()) || Objects.equals(businessType, RED_WRITE_OFF_PREPAYMENT.getBusinessType()) || Objects.equals(businessType, RED_WRITE_OFF_BALANCE.getBusinessType()) || Objects.equals(businessType, RED_WRITE_OFF.getBusinessType());
    }

    /**
     * 根据businessType判断是否为已核销/预收款类型
     * @param businessType 业务code
     * @return 是否为已核销/预收款类型
     * @author zhouwq
     * @date 2019/12/12 11:35
     */
    public static boolean isWriteOffByBusinessType(Integer businessType) {
        return Objects.equals(businessType, WRITE_OFF.getBusinessType()) || Objects.equals(businessType, WRITE_OFF_PREPAYMENT.getBusinessType()) || Objects.equals(businessType, PREPAYMENT.getBusinessType());
    }

    /**
     * 根据回款单类型判断是否为坏账类型
     *
     * @param type 回款单类型
     * @return boolean
     * @author 徐俊杰
     * @date 2019/11/21 14:35
     * @since v1.0
     */
    public static boolean isBad(String type) {
        return Objects.equals(BAD_PAYMENT.code, type);
    }

    /**
     * 通过枚举 businessType 获得枚举
     *
     * @param businessType 业务code
     *
     * @return XbbRefTypeEnum
     */
    public static PaymentSheetTypeEnum getByBusinessType(Integer businessType) {
        if (Objects.equals(businessType, XbbRefTypeEnum.PREPAYMENT_BALANCE.getCode())) {
            //如果是预收款列表类型，则也返回预收款枚举：预收款余额是一个单独的列表，有自己的XbbRefTypeEnum，但是其本质还是预收款类型
            return PREPAYMENT;
        }
        for (PaymentSheetTypeEnum cacheCode : values()) {
            if (Objects.equals(businessType, cacheCode.getBusinessType())) {
                return cacheCode;
            }
        }
        return UNKNOWN;
    }

    /**
     * 判断是否是创建/编辑回款单
     * @param sheetTypeEnum 回款单/付款单 类型总枚举
     * @return boolean true 创建/编辑回款单，false 不是任何一种回款单业务
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static boolean validateSheet(SheetTypeEnum sheetTypeEnum) {
        return sheetTypeEnum != null && Objects.equals(sheetTypeEnum.getXbbRefTypeEnum(), XbbRefTypeEnum.PAYMENT_SHEET);
    }

    public static PaymentSheetTypeEnum getByCode(String code) {
        for (PaymentSheetTypeEnum cacheCode : values()) {
            if (Objects.equals(code, cacheCode.getCode())) {
                return cacheCode;
            }
        }
        return UNKNOWN;
    }

    /**
     * 中文名称获取枚举
     *
     * @param name 名称
     * @return com.xbongbong.paas.enums.PaymentSheetTypeEnum
     * @author 徐俊杰
     * @date 2019/11/21 14:48
     * @since v1.0
     */
    public static PaymentSheetTypeEnum getByName(String name) {
        for (PaymentSheetTypeEnum cache : values()) {
            if (Objects.equals(name, cache.getName())) {
                return cache;
            }
        }
        return UNKNOWN;
    }

    /**
     * 获取非坏账的codeList
     *
     * @return java.util.List<com.sun.org.apache.xpath.internal.operations.String>
     * @author 徐俊杰
     * @date 2019/11/25 14:52
     * @since v1.0
     */
    public static List<String> getNotBadCodeList() {
        List<String> notBadCodeList = new ArrayList<>();
        for (PaymentSheetTypeEnum cache : values()) {
            if (Objects.equals(PaymentSheetTypeEnum.BAD_PAYMENT, cache) || Objects.equals(PaymentSheetTypeEnum.UNKNOWN, cache)) {
                continue;
            }
            notBadCodeList.add(cache.code);
        }
        return notBadCodeList;
    }

    /**
     * 回款核销只统计4种：已核销、预收款核销、红冲已核销、红冲预收款核销
     * @return java.util.List<java.lang.String>
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static List<String> getWriteOffCodeList(){
        return Arrays.asList(WRITE_OFF.code, WRITE_OFF_PREPAYMENT.code, RED_WRITE_OFF.code, RED_WRITE_OFF_PREPAYMENT.code, RED_WRITE_OFF_BALANCE.code);
    }

    /**
     * 获取资金账户收支情况的codeList
     *
     * @return java.util.List<java.lang.String>
     * @author 徐俊杰
     * @date 2020/3/18 15:29
     * @since v1.0
     */
    public static List<String> getCodeList4FundAccount() {
        List<String> codeList = new ArrayList<>();
        for (PaymentSheetTypeEnum cache : values()) {
            //不影响资金账户的类型：预收款核销、坏账、红冲预收款核销(退到余额)
            if (Objects.equals(PaymentSheetTypeEnum.WRITE_OFF_PREPAYMENT, cache) || Objects.equals(PaymentSheetTypeEnum.BAD_PAYMENT, cache) || Objects.equals(PaymentSheetTypeEnum.RED_WRITE_OFF_BALANCE, cache) || Objects.equals(PaymentSheetTypeEnum.UNKNOWN, cache)) {
                continue;
            }
            codeList.add(cache.code);
        }
        return codeList;
    }

    /**
     * 得到影响预收款余额的类型
     * @return java.util.List<java.lang.String>
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static List<Object> getCodeList4Balance() {
        //得到影响预收款余额的类型
        return Arrays.asList(PREPAYMENT.getCode(), WRITE_OFF_PREPAYMENT.getCode(), RED_WRITE_OFF_BALANCE.getCode(), RED_PREPAYMENT.getCode());
    }

    /**
     * 红冲类型
     *
     * @return java.util.List<java.lang.String>
     * @author 徐俊杰
     * @date 2019/12/5 11:11
     * @since v1.0
     */
    public static List<String> getRedCodeList() {
        return Arrays.asList(RED_WRITE_OFF.code, RED_WRITE_OFF_PREPAYMENT.code, RED_WRITE_OFF_BALANCE.code, RED_PREPAYMENT.code);
    }

    /**
     * 坏账类型
     *
     * @return java.util.List<java.lang.String>
     * @author 徐俊杰
     * @date 2019/12/5 11:12
     * @since v1.0
     */
    public static List<String> getBadCodeList() {
        return Collections.singletonList(BAD_PAYMENT.code);
    }

    /**
     * 客户关联回款单穿透页展示类型
     *
     *
     * @return java.util.List<java.lang.String>
     * @author 徐俊杰
     * @date 2019/12/25 22:09
     * @since v1.0
     */
    public static List<String> getCodeListForCustomer() {
        return Arrays.asList(WRITE_OFF.code, PREPAYMENT.code, RED_WRITE_OFF.code, RED_WRITE_OFF_PREPAYMENT.code, RED_WRITE_OFF_BALANCE.code, RED_PREPAYMENT.code, BAD_PAYMENT.code);
    }

    /**
     * 客户关联回款单回款金额求和的类型
     *
     * @return java.util.List<java.lang.String>
     * @author 徐俊杰
     * @date 2020/1/7 14:56
     * @since v1.0
     */
    public static List<String> getCodeListForCustomerSum() {
        return Arrays.asList(WRITE_OFF.code, PREPAYMENT.code, RED_WRITE_OFF.code, RED_WRITE_OFF_PREPAYMENT.code, RED_WRITE_OFF_BALANCE.code, RED_PREPAYMENT.code);
    }

    /**
     * PK榜+业绩目标
     * 不统计预收款，红冲预收款余额，坏账
     *
     * @return java.util.List<java.lang.String>
     * @author 徐俊杰
     * @date 2019/12/27 9:52
     * @since v1.0
     */
    public static List<String> getCodeListForPK() {
        return Arrays.asList(WRITE_OFF.code, WRITE_OFF_PREPAYMENT.code, RED_WRITE_OFF.code, RED_WRITE_OFF_PREPAYMENT.code, RED_WRITE_OFF_BALANCE.code);
    }

    /**
     * 根据普通回款单类型code，得到对应的红冲类型的XbbRefTypeEnum的code
     * @param code 回款单类型type
     * @return java.lang.String
     * @author zcp
     * @date 19/12/2 002 19:39
     * @update 19/12/2 002 19:39
     * @since v1.0
     * @version v1.0
     */
    public static Integer getRedBusinessTypeByCode(String code) {
        if (Objects.equals(code, WRITE_OFF.code)) {
            //code为已核销，则返回【红冲】已核销的businessType
            return RED_WRITE_OFF.businessType;
        } else if (Objects.equals(code, WRITE_OFF_PREPAYMENT.code)) {
            //code为预收款核销，则默认返回【红冲】预收款核销的businessType；如果要【红冲(退到余额)】，则直接用BusinessDetailButtonEnum.PAYMENT_SHEET_RED_BALANCE的businessType即可
            return RED_WRITE_OFF_PREPAYMENT.businessType;
        } else if (Objects.equals(code, PREPAYMENT.code)) {
            //code为预收款，则返回【红冲】预收款的businessType
            return RED_PREPAYMENT.businessType;
        }
        return UNKNOWN.businessType;
    }

    /**
     * 根据普通回款单类型code，得到其本身的businessType
     * 回款单编辑、删除、打印按钮，要基于回款单类型得到businessType：因为回款单详情打开前端拿到的都是702，而要根据回款单data内的paymentSheetType确定具体是哪种类型回款单
     * @param code
     * @return java.lang.Integer
     * @author zcp
     * @date 19/12/3 003 16:20
     * @update 19/12/3 003 16:20
     * @since v1.0
     * @version v1.0
     */
    public static Integer getBusinessTypeByCode(String code) {
        PaymentSheetTypeEnum paymentSheetTypeEnum = getByCode(code);
        return paymentSheetTypeEnum.businessType;
    }

    /**
     * 得到所有预收款相关类型code集合
     * （当预收款菜单未开启时，所有预收款相关的回款单类型都应该隐藏）
     * @return java.util.List<java.lang.String>
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static List<String> getPrepaymentCodeList() {
        return Arrays.asList(WRITE_OFF_PREPAYMENT.code, PREPAYMENT.code, RED_WRITE_OFF_PREPAYMENT.code, RED_WRITE_OFF_BALANCE.code, RED_PREPAYMENT.code);
    }

    /**
     * 强制进入审批的回款单类型（4种红冲）
     * @return java.util.List<java.lang.Object> 审批条件ConditionsEntityExt.value字段需要的是List<Object>
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static List<Object> mustIntoProcess(){
        return Arrays.asList(RED_WRITE_OFF.getCode(), RED_WRITE_OFF_PREPAYMENT.getCode(), RED_PREPAYMENT.getCode(), RED_WRITE_OFF_BALANCE.getCode());
    }

    public String getName() {
        return I18nMessageUtil.getMessage(name);
    }
    public String getI18nName() {
        return name;
    }
    /**
     *
     * @Description: 获取所有回款单类型的业务code
     * @param
     * @return: java.util.List<java.lang.Integer>
     * @Author: shen.yang
     * @Date: 2022/3/29  15:56
    */
    public static List<Integer> getAllBusinessType(){
        return Arrays.stream(PaymentSheetTypeEnum.values()).filter(v -> !Objects.equals(v.getCode(),UNKNOWN.getCode())).map(PaymentSheetTypeEnum::getBusinessType).collect(Collectors.toList());
    }
    /**
     *
     * @Description: 获取除去预收款和红冲预收款余额之外的所有回款单code（用于团队继承）
     * @param
     * @return: java.util.List<java.lang.Integer>
     * @Author: shen.yang
     * @Date: 2022/3/29  16:02
    */
    public static List<Integer> getBusinessTypeExcludePre(){
        return getAllBusinessType().stream().filter(v -> !Arrays.asList(PREPAYMENT.getBusinessType(),RED_PREPAYMENT.getBusinessType()).contains(v)).collect(Collectors.toList());
    }

}
